package com.wanban.download.utils

import android.annotation.SuppressLint
import android.text.TextUtils
import android.util.Log
import com.wanban.download.Params
import com.wanban.download.WBDownloadUtils
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.FileNotFoundException
import java.io.InterruptedIOException
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSession
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

/**
 * OkHttpClient Provider
 * 提供唯一的okHttpClient，防止多次调用，破坏OkHttp内部的线程池等
 */
object OkHttpClientUtils {

    private val client by lazy {
        val clientBuilder = OkHttpClient.Builder()
            .connectTimeout(Params.HTTP_CONNECT_TIMEOUT, TimeUnit.SECONDS)
            .readTimeout(Params.HTTP_READ_TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(Params.HTTP_WRITE_TIMEOUT, TimeUnit.SECONDS)
            .hostnameVerifier(hostnameVerifier)//配置
            .sslSocketFactory(sSLSocketFactory, x509TrustManager)//配置
            .addInterceptor { chain ->
                // 以拦截到的请求为基础建立一个新的请求对象，而后插入Header
                val requestBuilder = chain.request().newBuilder()
                    .addHeader("Accept", "*/*")
                // 开始请求
                return@addInterceptor chain.proceed(requestBuilder.build())
            }
            .addInterceptor(RetryInterceptor(Params.MAX_HTTP_RETRY_TIMES))
        return@lazy clientBuilder.build()
    }

    private fun getOkHttpClient(): OkHttpClient {
        return client
    }

    fun openSync(request: Request): Response?{
        var response: Response? = null
        try {
            val call = getOkHttpClient().newCall(request)
            response = call.execute()
            return if (response.isSuccessful) {
                response
            } else {
                null
            }
        } catch (e: InterruptedIOException) { // 中断异常不处理
            response?.close()
            return response
        } catch (e: InterruptedException) {  // 中断异常不处理
            response?.close()
            return response
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
            response?.close()
            return response
        } catch (e: okio.IOException) {
            e.printStackTrace()
            response?.close()
            return response
        } catch (e: java.io.IOException) {
            e.printStackTrace()
            response?.close()
            return response
        } catch (e: NullPointerException) {
            e.printStackTrace()
            response?.close()
            return response
        } catch (e: TimeoutException) {
            e.printStackTrace()
            response?.close()
            return response
        } catch (e: Exception) {
            e.printStackTrace()
            response?.close()
            return response
        }
    }

    fun openSync(url: String?, header: Map<String, String?>? = null): Response?{
         if (TextUtils.isEmpty(url)) return null
         var response: Response? = null
         try {
             val request = Request.Builder().url(url!!)
             header?.keys?.forEach { key ->
                 val value = header[key]
                 if (value != null) {
                     request.addHeader(key, value)
                 }
             }
             val call = getOkHttpClient().newCall(request.build())
             response = call.execute()
             if (response.isSuccessful) {
                 return response
             } else {
                 return null
             }
         } catch (e: InterruptedIOException) { // 中断异常不处理
             response?.close()
             return response
         } catch (e: InterruptedException) {  // 中断异常不处理
             response?.close()
             return response
         } catch (e: FileNotFoundException) {
             e.printStackTrace()
             response?.close()
             return response
         } catch (e: okio.IOException) {
             e.printStackTrace()
             response?.close()
             return response
         } catch (e: java.io.IOException) {
             e.printStackTrace()
             response?.close()
             return response
         } catch (e: NullPointerException) {
             e.printStackTrace()
             response?.close()
             return response
         } catch (e: TimeoutException) {
             e.printStackTrace()
             response?.close()
             return response
         } catch (e: Exception) {
             e.printStackTrace()
             response?.close()
             return response
         }
     }

    private class RetryInterceptor(retry: Int) : Interceptor {

        private var maxRetry = 3 //最大重试次数
        private var retryNum = 0

        init {
            if (retry > 0) maxRetry = retry
        }

        override fun intercept(chain: Interceptor.Chain): Response {
            val request = chain.request()
            var response = chain.proceed(request)
            while (!response.isSuccessful && retryNum < maxRetry) {
                retryNum++
                response.close()
                response = chain.proceed(request)
            }
            retryNum = 0
            return response
        }
    }

    // SSL处理
    private val hostnameVerifier: HostnameVerifier
        //获取HostnameVerifier
        get() = HostnameVerifier { _: String?, _: SSLSession? -> true }


    private val x509TrustManager: X509TrustManager
        get() = @SuppressLint("CustomX509TrustManager")
        object : X509TrustManager {
            @SuppressLint("TrustAllX509TrustManager")
            override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
            }
            @SuppressLint("TrustAllX509TrustManager")
            override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
            }

            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }
        }

    private val sSLSocketFactory: SSLSocketFactory
        //获取这个SSLSocketFactory
        get() {
            try {
                val sslContext = SSLContext.getInstance("SSL")
                sslContext.init(null, trustManager, SecureRandom())
                return sslContext.socketFactory
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
        }
    private val trustManager: Array<TrustManager>
        //获取TrustManager
        get() = arrayOf(@SuppressLint("CustomX509TrustManager")
        object : X509TrustManager {
            @SuppressLint("TrustAllX509TrustManager")
            override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
            }

            @SuppressLint("TrustAllX509TrustManager")
            override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
            }

            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }
        })
}